home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / UTILITY / CMDED2E6.ARJ / DIRS.ASM < prev    next >
Assembly Source File  |  1992-06-30  |  13KB  |  558 lines

  1. ; DIRS.ASM
  2. ; (c) 1989, 1990 Ashok P. Nadkarni
  3. ;
  4. ;This module implements the directory stack feature of the cmdedit program.
  5.  
  6.     INCLUDE ascii.inc
  7.     INCLUDE common.inc
  8.     INCLUDE general.inc
  9.     INCLUDE    buffers.inc
  10.     INCLUDE dos.inc
  11.     INCLUDE bios.inc
  12.  
  13.     PUBLIC    dirs_init
  14.     PUBLIC    execute_popd
  15.     PUBLIC    execute_pushd
  16.     PUBLIC    execute_chd
  17.     PUBLIC    execute_rstdir
  18.     PUBLIC    execute_dirstat        ;added by wd
  19.     PUBLIC    execute_backdir        ;added by wd
  20.     PUBLIC    enable_dircmds
  21.  
  22. PATHBUF_SIZE EQU 68
  23.  
  24. CSEG    SEGMENT    PARA PUBLIC 'CODE'
  25.  
  26.     EXTRN    user_command:BYTE
  27.     EXTRN    in_appl:BYTE
  28.     EXTRN    linebuf:BYTE        ;line buffer
  29.     EXTRN    backbuf:BYTE        ;back-dir buffer - added by wd
  30.     EXTRN    lastchar:WORD
  31.     EXTRN    dirstk_error:BYTE
  32.     EXTRN    resident:BYTE
  33.     EXTRN    abort_install:PROC
  34.     EXTRN    abort_processing:PROC
  35.     EXTRN    skip_whitespace:PROC
  36.     EXTRN    skip_nonwhite:PROC
  37.     EXTRN    tolower:PROC
  38.  
  39. dir_stk    $string_stack   <>        ;Buffer descriptors
  40. enable_dircmds    db    1        ;If 1, enables directory commands
  41. ;                     even if caller is not DOS
  42.  
  43. DGROUP    GROUP    CSEG
  44.     ASSUME    CS:DGROUP,DS:DGROUP,ES:DGROUP,SS:DGROUP
  45.  
  46.  
  47. ;+
  48. ; FUNCTION : dirs_init
  49. ;
  50. ; Initializes the various data structures associated with the
  51. ; directory stack buffer. CALLER MUST ENSURE PASSED ADDRESSES ARE VALID
  52. ; AND BUFFER IS LARGE ENOUGH.
  53. ;
  54. ; Parameters:
  55. ;    AX     - length of buffer in bytes
  56. ;    BX    - address of buffer
  57. ;
  58. ; Returns:
  59. ;    AX =    0 if no errors
  60. ;        -1 otherwise
  61. ; Registers destroyed : BX
  62. ;-
  63. dirs_init proc    near
  64.     push    bx
  65.     mov    bx,offset DGROUP:dir_stk ;bx := address of buffer descriptors
  66.     xchg    ax,cx            ;CX = buffer size
  67.     pop    ax            ;AX = Buffer address
  68.                     ;BX points to appropriate descriptor
  69.     call    near ptr strstk_init    ;Initialize buffer and descriptor
  70.     ret
  71. dirs_init    endp
  72.  
  73.  
  74. ;+
  75. ; FUNCTION: execute_rstdir
  76. ;
  77. ;    Called to reset the directory stack.
  78. ;
  79. ; Parameters:
  80. ;    None.
  81. ;-
  82. execute_rstdir proc near
  83.     mov    bx,offset DGROUP:dir_stk
  84.     call    near ptr strstk_reset
  85.     ret
  86. execute_rstdir endp
  87.  
  88. ;+
  89. ; FUNCTION : dir_push
  90. ;
  91. ;    Called to push a drive and path onto the directory stack. The
  92. ;    string must end in a 0 byte.
  93. ;
  94. ; Parameters:
  95. ;    DX    ->string to push
  96. ;
  97. ; Returns:
  98. ;    CF    = 1 if errors
  99. ;          0 no errors
  100. ;
  101. ; Register(s) destroyed:
  102. ;    AX,BX,CX,DX
  103. ;-
  104. dir_push proc    near
  105.     @save    di
  106.     mov    di,dx                ;di->string
  107.     mov    cx,0ffffh
  108.     xor    al,al
  109.     repne    scasb
  110.     mov    ax,cx
  111.     not    ax                ;AX<-length of string
  112. ;                         including null terminator
  113.     mov    bx,offset DGROUP:dir_stk
  114.     xor    cx,cx                ;Don't force push
  115.     call    near ptr strstk_push        ;Params AX,BX,CX,DX
  116.     ; strstk_push sets/resets CF
  117.     @restore
  118.     ret
  119. dir_push endp
  120.  
  121. ;+
  122. ; FUNCTION : abort_dir_op
  123. ;
  124. ;    Called to abort a directory stack operation. Action taken
  125. ;    depends on whether the program is already resident or is being
  126. ;    installed. This routine does NOT return to caller.
  127. ;
  128. ; Parameters:
  129. ;    AX    = code to pass to abort_processing
  130. ;
  131. ; Returns:
  132. ;    Nothing.
  133. ; Register(s) destroyed:
  134. ;-
  135. abort_dir_op proc near
  136.     mov    dx,offset DGROUP:abort_processing
  137.     cmp    resident,0
  138.     jne    @abort_dir_op_90        ;Jump if resident
  139.     @DispStr dirstk_error
  140.     mov    dx,offset DGROUP:abort_install
  141. @abort_dir_op_90:
  142.     jmp    dx
  143. abort_dir_op endp
  144.  
  145.  
  146.  
  147.  
  148. ;+
  149. ; FUNCTION : check_dircmd_allowed
  150. ;
  151. ;    Makes sure DOS is the caller or directory commands have been
  152. ;    enabled for all applications and returns. Else aborts.
  153. ;
  154. ; Parameters:
  155. ;    None.
  156. ;
  157. ; Returns:
  158. ;    Nothing.
  159. ; Register(s) destroyed:
  160. ;     AX
  161. ;-
  162. check_dircmd_allowed proc near
  163.     cmp    enable_dircmds,1
  164.     je    @check_dircmd_allowed_99
  165.     mov    ax,E_DIRSTK_DOS            ;Assume error
  166.     cmp    in_appl,1            ;In application ?
  167.     je    abort_dir_op            ;Yes, abort
  168. @check_dircmd_allowed_99:                    ;Else return
  169.     ret
  170. check_dircmd_allowed endp
  171.  
  172.  
  173. ;+
  174. ; FUNCTION : save_drv_path
  175. ;
  176. ;    Saves the current drive and path in the specified buffer in the
  177. ;    form `D:\dir1....' where the current drive letter. The buffer
  178. ;    MUST be long enough.
  179. ;
  180. ; Parameters:
  181. ;    AX    = address of save buffer
  182. ;
  183. ; Returns:
  184. ;    Nothing.
  185. ;
  186. ; Register(s) destroyed:
  187. ;    AX,DX
  188. ;-
  189. save_drv_path    proc near
  190.     @save    si,di
  191.     mov    di,ax                ;DI->save buffer
  192.     @GetDrv                    ;AL<-drive number
  193.     add    al,'A'        ;AL<-drive letter. wd changed 'a' to 'A'
  194.     stosb                    ;Remember current drive
  195.     mov    al,':'
  196.     stosb
  197.     mov    al,'\'
  198.     stosb
  199.     @GetDir di                ;Remember current path
  200.     @restore
  201.     ret
  202. save_drv_path    endp
  203.  
  204.  
  205.  
  206. ;+
  207. ; FUNCTION : change_drv_path
  208. ;
  209. ;    Changes the current drive and directory to the one specified.
  210. ;
  211. ; Parameters:
  212. ;    AX    ->path in the form `D:\dir1\dir2\...' terminated
  213. ;          with a 0 byte where D is the drive letter. Entire
  214. ;          path name need no be given. It is OK if the last
  215. ;          directory in the path is followed by a '\' or a '/'.
  216. ;
  217. ; Returns:
  218. ;    CF    = 0 if current drive and directory succesfully changed,
  219. ;          1 if any errors (drive and path both unchanged)
  220. ; Register(s) destroyed:
  221. ;-
  222. change_drv_path proc near
  223.     @save    si,di
  224.     push    bp
  225.     mov    bp,sp
  226.     sub    sp,PATHBUF_SIZE
  227. cur_path    equ <byte ptr [bp-PATHBUF_SIZE]>
  228.     push    ax                ;Remember new path
  229.     lea    ax,cur_path            ;AX->current path save buf
  230.     call    near ptr save_drv_path        ;Save current disk/dir
  231.     pop    dx                ;DX->new path
  232.     mov    si,dx                ;SI->new path
  233.     mov    di,dx
  234.     xor    al,al                ;Search for terminator
  235.     mov    cx,0ffffh
  236.     repne    scasb                ;DI->byte after NULL
  237.     mov    ah,[di-2]            ;AL=byte before NULL
  238.     cmp    ah,'\'                ;Extra '\' char ?
  239.     je    @change_drv_path_5        ;Yes
  240.     cmp    ah,'/'                ;Extra '/' char ?
  241.     jne    @change_drv_path_10        ;No
  242. @change_drv_path_5:
  243.     ;If '\' at the end, make sure it is not of the form d:\ or just \
  244.     cmp    byte ptr [di-3],':'
  245.     je    @change_drv_path_10
  246.     dec    di
  247.     dec    di                ;DI->'\' character
  248.     cmp    di,dx                ;Solitary '\' ?
  249.     je    @change_drv_path_10        ;Yes
  250.     mov    [di],al                ;No, replace '\' with 0
  251. @change_drv_path_10:
  252.     @ChDir    dx
  253.     jnc    @change_drv_path_80        ;No error
  254. ;     Check if error was because drive was specified but not the path.
  255. ;    In this case, we should only change the drive.
  256.     cmp    byte ptr 2[si],0        ;third byte nust be null
  257.     jne    @change_drv_path_85        ;Nope
  258.     cmp    byte ptr 1[si],':'        ;Drive specified ?
  259.     jne    @change_drv_path_85        ;Nope
  260.     jmp    short @change_drv_path_82
  261. @change_drv_path_80:
  262.     cmp    byte ptr 1[si],':'        ;Drive spec ?
  263.     clc                    ;To indicate success
  264.     jne    @change_drv_path_99        ;No, all done
  265. @change_drv_path_82:
  266.     lodsb                    ;AL<-drive
  267.     call    near ptr tolower
  268.     sub    al,'a'                ;AL<-drive number
  269.     @SetDrv al                ;Change the drive
  270.     jnc    @change_drv_path_99        ;No error
  271. ;     Error, restore path, drive would not have been changed
  272. @change_drv_path_85:
  273.     lea    dx,cur_path
  274.     @ChDir    dx
  275.     stc                    ;Indicate error to caller
  276. @change_drv_path_99:
  277.     mov    sp,bp
  278.     pop    bp
  279.     @restore
  280.     ret
  281. change_drv_path endp
  282.  
  283.  
  284.  
  285. ;+
  286. ; FUNCTION : execute_backdir by wd
  287. ;
  288. ;    Go to the previously visited directory.
  289. ;
  290. ; Parameters:
  291. ;    None.
  292. ;
  293. ; Returns:
  294. ;    Nothing.
  295. ;
  296. ; Register(s) destroyed:
  297. ;    AX,BX,CX,DX
  298. ;-
  299. execute_backdir proc near
  300.     call    near ptr check_dircmd_allowed
  301.     lea    bx,backbuf
  302.     cmp    byte ptr [bx],0
  303.     je    @execute_backdir_99
  304.     mov    dx,bx
  305.     call    near ptr dir_push
  306.     xor    cx,cx
  307.     jmp    short execute_popd
  308. @execute_backdir_99:
  309.     ret
  310. execute_backdir endp
  311.  
  312.  
  313.  
  314. ;+
  315. ; FUNCTION : execute_popd
  316. ;
  317. ;    Pops the topmost element off the directory stack and makes it
  318. ;    the current drive/directory.
  319. ;
  320. ; Parameters:
  321. ;    None.
  322. ;
  323. ; Returns:
  324. ;    Nothing.
  325. ;
  326. ; Register(s) destroyed:
  327. ;    AX,BX,CX,DX
  328. ;-
  329. execute_popd proc near
  330.     call    near ptr check_dircmd_allowed
  331.     @save    si,di
  332.     push    bp
  333.     mov    bp,sp
  334.     sub    sp,PATHBUF_SIZE
  335. topdir    equ    PATHBUF_SIZE
  336.     lea    ax,backbuf            ;this and next line added by wd
  337.     call    near ptr save_drv_path
  338.     mov    bx,offset DGROUP:dir_stk    ;BX->dir stack descriptor
  339.     call    near ptr strstk_settop
  340.     lea    ax,[bp-topdir]
  341.     mov    cx,PATHBUF_SIZE
  342.     call    near ptr strstk_copy        ;Get top of stack
  343. ;                         String is terminated
  344. ;                         by a 0 byte
  345.     jc    @execute_popd_90
  346.     or    ax,ax                ;Empty stack ?
  347.     jz    @execute_popd_90        ;Yes, error
  348.     lea    ax,[bp-topdir]            ;AX->new path
  349.     call    near ptr change_drv_path    ;Change drive and path
  350.     jc    @execute_popd_90
  351.     call    near ptr strstk_kill        ;Delete top of stack
  352.     mov    sp,bp
  353.     pop    bp
  354.     @restore
  355. ; Klugery - return a zero length string to DOS in order to set prompt properly.
  356.     mov    lastchar,offset DGROUP:linebuf
  357.     mov    user_command,1            ;indicate line to be
  358. ;                         returned to DOS
  359.     ret
  360.  
  361. @execute_popd_90:
  362.     mov    ax,E_DIRSTK_EMPTY
  363.     jmp    near ptr abort_dir_op
  364. execute_popd    endp
  365.  
  366.  
  367.  
  368. ;+
  369. ; FUNCTION : execute_pushd
  370. ;
  371. ;    If a parameter is given, pushes current directory/disk onto the
  372. ;    dir stack and changes to the parameter. If no parameter,
  373. ;    exchange the top of directory stack with current disk-directory.
  374. ;
  375. ; Parameters:
  376. ;    SI    -> first char in linebuf following this command
  377. ;    CX    = remaining num chars in line
  378. ;
  379. ; Returns:
  380. ;    Nothing.
  381. ;
  382. ; Register(s) destroyed:
  383. ;    AX,BX,CX,DX
  384. ;-
  385. execute_pushd    proc    near
  386.     @save    si,di
  387.     push    bp
  388.     mov    bp,sp
  389. ;    sub sp,2*PATHBUF_SIZE
  390. ;cur_path    equ <byte ptr [bp-PATHBUF_SIZE]>
  391. ;new_path    equ <byte ptr [bp-(2*PATHBUF_SIZE)]>
  392. ;wd replaced above 3 lines by following 2 lines:
  393.     sub    sp,PATHBUF_SIZE
  394. new_path    equ <byte ptr [bp-PATHBUF_SIZE]>
  395.  
  396.     call    near ptr check_dircmd_allowed
  397. ;                         Will return only if so
  398. ;    push    cx        ;Save line length
  399. ;    lea    ax,cur_path
  400. ;wd replaced above 2 lines by following line:
  401.     lea    ax,backbuf
  402.  
  403.     call    near ptr save_drv_path        ;Save current drive and path
  404.  
  405. ;    pop    cx        ;CX<-restored line length (removed by wd)
  406.     call    near ptr skip_whitespace
  407.     ; SI->first non blank, CX<-num remaining chars
  408.     jcxz    @execute_pushd_50        ;Exchange directory
  409. ;                         with top of stack
  410.     push    si                ;SI->path to change to
  411.     call    near ptr skip_nonwhite
  412.     ; SI->first non-blank
  413.     mov    byte ptr [si],0            ;Terminating 0 byte
  414. ;    We are guaranteed place for a 0 because of the dummy byte after linebuf
  415.     pop    ax                ;AX->dir to change to
  416.     call    near ptr change_drv_path    ;Change path and drive
  417.     jc    @execute_pushd_32        ;Error
  418. @execute_pushd_25:
  419. ;    lea    dx,cur_path            ;changed to line below by wd
  420.     lea    dx,backbuf
  421.     call    near ptr dir_push        ;Push onto stack
  422.     jnc    @execute_pushd_100        ;No error
  423. @execute_pushd_30:
  424. ; Error. Restore original directory and display error message.
  425. ;    lea    ax,cur_path            ;changed to line below by wd
  426.     lea    ax,backbuf
  427.     call    near ptr change_drv_path
  428. @execute_pushd_32:
  429.     mov    ax,E_DIRSTK
  430.     jmp    abort_dir_op
  431.  
  432. @execute_pushd_50:
  433. ; Exhange current directory with the directory at the top of the stack
  434.     mov    bx,offset DGROUP:dir_stk    ;BX->dir stack descriptor
  435.     call    near ptr strstk_settop
  436.     lea    ax,new_path
  437.     mov    cx,PATHBUF_SIZE
  438.     call    near ptr strstk_copy        ;Get top of stack
  439. ;                         String is terminated
  440. ;                         by a 0 byte
  441.     jnc    @execute_pushd_60
  442. @execute_pushd_55:
  443. ;    lea    ax,cur_path            ;changed to line below by wd
  444.     lea    ax,backbuf
  445.     call    near ptr change_drv_path
  446.     mov    ax,E_DIRSTK_EMPTY
  447.     jmp    abort_dir_op
  448. @execute_pushd_60:
  449.     or    ax,ax                ;Empty stack ?
  450.     jz    @execute_pushd_55        ;Yes, error
  451.     lea    ax,new_path            ;AX->new path
  452.     call    near ptr change_drv_path    ;Change drive and path
  453.     jc    @execute_pushd_30
  454.     call    near ptr strstk_kill        ;Delete top of stack
  455. ;    lea    dx,cur_path             ;changed to line below by wd
  456.     lea    dx,backbuf
  457.     call    near ptr dir_push
  458.     jnc    @execute_pushd_100            ;All set
  459. ;    Error. Restore original top of stack
  460.     lea    dx,new_path
  461.     call    near ptr dir_push        ;Push must succeed
  462.     jmp    short @execute_pushd_30
  463.  
  464. @execute_pushd_100:
  465.     mov    sp,bp
  466.     pop    bp
  467.     @restore
  468. ; Klugery - return a zero length string to DOS in order to set prompt properly.
  469.     mov    lastchar,offset DGROUP:linebuf
  470.     mov    user_command,1            ;indicate line to be
  471. ;                         returned to DOS
  472.     ret
  473. execute_pushd    endp
  474.  
  475.  
  476.  
  477.  
  478. ;+
  479. ; FUNCTION : execute_chd
  480. ;
  481. ;    Changes to the disk and directory specified as parameter.
  482. ;
  483. ; Parameters:
  484. ;    SI    -> first char in linebuf following this command
  485. ;    CX    = remaining num chars in line
  486. ;
  487. ; Returns:
  488. ;    Nothing.
  489. ;
  490. ; Register(s) destroyed:
  491. ;    AX,BX,CX,DX
  492. ;-
  493. execute_chd    proc    near
  494.     @save    si,di
  495.     push    bp
  496.     mov    bp,sp
  497.     sub    sp,PATHBUF_SIZE
  498. new_path    equ <byte ptr [bp-PATHBUF_SIZE]>
  499.     call    near ptr check_dircmd_allowed
  500. ;                         Will return only if so
  501. ;    push    cx        ;Save line length ;wd replaced by next 2 lines
  502.     lea    ax,backbuf
  503.     call    near ptr save_drv_path        ;Save current drive and path
  504.  
  505.     call    near ptr skip_whitespace
  506.     ; SI->first non blank, CX<-num remaining chars
  507.     jcxz    @execute_chd_100        ;No args
  508. ;                         with top of stack
  509.     push    si                ;SI->path to change to
  510.     call    near ptr skip_nonwhite
  511.     ; SI->first non-blank
  512.     mov    byte ptr [si],0            ;Terminating 0 byte
  513. ;    We are guaranteed place for a 0 because of the dummy byte after linebuf
  514.     pop    ax                ;AX->dir to change to
  515.     call    near ptr change_drv_path    ;Change path and drive
  516.     jnc    @execute_chd_100            ;No error
  517.     mov    ax,E_DIRSTK
  518.     jmp    abort_dir_op
  519.  
  520. @execute_chd_100:
  521.     mov    sp,bp
  522.     pop    bp
  523.     @restore
  524. ; Klugery - return a zero length string to DOS in order to set prompt properly.
  525.     mov    lastchar,offset DGROUP:linebuf
  526.     mov    user_command,1            ;indicate line to be
  527. ;                         returned to DOS
  528.     ret
  529. execute_chd endp
  530.  
  531.  
  532. ;+
  533. ; FUNCTION : execute_dirstat by wd
  534. ;
  535. ;    This function outputs the entire directory stack.
  536. ;
  537. ; Parameters:
  538. ;    SI  -> first char in linebuf following this command
  539. ;    CX  == remaining num chars in the line
  540. ;
  541. ; Returns:
  542. ;    Nothing.
  543. ;
  544. ; Register(s) destroyed:
  545. ;    AX,BX,CX,DX
  546. ;-
  547. execute_dirstat proc near
  548.     mov    bx,offset DGROUP:dir_stk    ;BX->dir stack descriptor
  549.     call    near ptr strstk_output
  550.     ret
  551. execute_dirstat endp
  552.  
  553.  
  554.  
  555. CSEG    ENDS
  556.  
  557.     END
  558.